package com.ys.service.wallet.eth;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.ys.entity.WalletAddress;
import com.ys.entity.WalletDeposit;
import com.ys.entity.WalletWithdraw;
import com.ys.entity.block.Transaction;
import com.ys.entity.block.eth.EthTransaction;
import com.ys.entity.block.eth.EthTransactionReceipt;
import com.ys.enu.CurrencyEnum;
import com.ys.service.WalletAddressServiceImap;
import com.ys.service.WalletDepositServiceImap;
import com.ys.service.WalletWithdrawServiceImap;
import com.ys.service.wallet.AbstractWalletJobService;
import com.ys.service.wallet.eth.EthWalletServiceBase;
import com.ys.util.EthUtil;
import com.ys.util.HexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

/**
 *
 * 以太坊钱包定时服务
 *
 */
@Service
@Slf4j
public class EthService extends AbstractWalletJobService {
    @Autowired
    private WalletDepositServiceImap walletDepositServiceImap;
    @Autowired
    private WalletWithdrawServiceImap walletWithdrawServiceImap;
    @Autowired
    private WalletAddressServiceImap walletAddressServiceImap;
    @Autowired
    private EthWalletServiceBase ethWalletServiceBase;

    /**
     * 处理区块中的交易信息
     *
     * @param transactions
     */
    //TODO 交易信息可以放在mongo中
    public void dealBlock(List<EthTransaction> transactions) throws Exception {
        log.info("区块中的交易信息：" + JSONUtil.toJsonStr(transactions));
        for(EthTransaction e:transactions){
            String to=e.getTo();
            WalletAddress walletAddress=new WalletAddress();
            walletAddress.setAdress(to);
            EntityWrapper<WalletAddress> walletAddressEntityWrapper=new EntityWrapper<>(walletAddress);
            walletAddress=walletAddressServiceImap.selectOne(walletAddressEntityWrapper);
            if(walletAddress==null){
                log.info("此充值地址不在钱包内：to="+e.getTo());
                continue;
            }

            if(StrUtil.isBlank(e.getTo())){
                log.info("此条记录是合约创建记录:txhash="+e.getHash());
                continue;
            }
            if(StrUtil.isBlank(e.getBlockHash())){
                log.info("此条记录的状态是pending:txhash="+e.getHash());
                continue;
            }
            //判断是否是 智能合约
            CurrencyEnum currencyEnum=CurrencyEnum.parseCurrency(walletAddress.getCurrency());

            EthTransactionReceipt ethTransactionReceipt=ethWalletServiceBase.ethGetTransactionReceipt(e.getHash());

            if(StrUtil.isNotBlank(ethTransactionReceipt.getContractAddress())){
                currencyEnum=CurrencyEnum.parseContractAddress(ethTransactionReceipt.getContractAddress());
                if(currencyEnum==null){
                    log.warn("不支持的合约地址："+ethTransactionReceipt.getContractAddress());
                    continue;
                }
            }

            WalletDeposit walletDeposit=new WalletDeposit();
            walletDeposit.setCurrency(currencyEnum.getCurrency());
            walletDeposit.setCurrencyChainType(currencyEnum.getCurrencyChainType());
            walletDeposit.setBlockNum(EthUtil.hexToInt(e.getBlockNumber()));
            walletDeposit.setDepositAmount(new BigDecimal(HexUtil.hexToBigInteger(e.getValue())));
            walletDeposit.setBlockHash(e.getHash());
            walletDeposit.setDepositFromAddress(e.getFrom());
            walletDeposit.setTenantId(walletAddress.getTenantId());
            walletDeposit.setDepositInt(HexUtil.hexToBigInteger(e.getValue()));
            walletDeposit.setGas(HexUtil.hexToBigInteger(e.getGas()));
            walletDeposit.setGasPrice(HexUtil.hexToBigInteger(e.getGasPrice()));
            walletDeposit.setJsonData(e.getInput());

            walletDeposit.setNonce(HexUtil.hexToBigInteger(e.getNonce()).toString());
            walletDeposit.setTransactionIndex(HexUtil.hexToBigInteger(e.getTransactionIndex()).toString());
            walletDeposit.setTxHash(e.getHash());

            walletDeposit.setDepositToAddress(e.getTo());

            HashMap<String,Object> jsonData=new HashMap<>();
            jsonData.put("s",e.getS());
            jsonData.put("v",e.getV());
            jsonData.put("r",e.getR());

            walletDeposit.setJsonData(JSONUtil.toJsonStr(jsonData));
            walletDepositServiceImap.insert(walletDeposit);

        }

    }

    /**
     * 更新冲提状态
     * @param currentBlockNum
     */
    public void updateDepositWithdrawStatus(Integer currentBlockNum){
        WalletDeposit walletDeposit=new WalletDeposit();
        walletDeposit.setCurrencyChainType(CurrencyEnum.ETH.getCurrencyChainType());
        walletDeposit.setBlockNum(currentBlockNum);
        int depositRow=walletDepositServiceImap.updateDepositStatus(walletDeposit,CurrencyEnum.ETH.getConfirmNum());
        log.info("以太坊链上此次冲提的冲币交易条数为 row="+depositRow);

        WalletWithdraw walletWithdraw=new WalletWithdraw();
        walletWithdraw.setCurrencyChainType(CurrencyEnum.ETH.getCurrencyChainType());
        walletWithdraw.setBlockNum(currentBlockNum);
        int withdrawRow=walletWithdrawServiceImap.updateWithdrawStatus(walletWithdraw,CurrencyEnum.ETH.getConfirmNum());
        log.info("以太坊链上此次更新的提币交易条数为 row="+withdrawRow);

    }

    /**
     * 处理交易hash
     * @param t
     */
    public void dealTransaction(Transaction t,WalletWithdraw walletWithdraw){
        EthTransaction transaction= (EthTransaction) t;

        if(transaction==null || StrUtil.isBlank(transaction.getBlockNumber()))
            return;
        WalletWithdraw updateBlockNum=new WalletWithdraw();

        updateBlockNum.setId(walletWithdraw.getId());
        updateBlockNum.setBlockNum(HexUtil.hexToInteger(transaction.getBlockNumber()));
        walletWithdrawServiceImap.updateById(updateBlockNum);
    }

    @Override
    public Transaction getTransaction() {
        return new EthTransaction();
    }




    @Override
    public Integer getCurrency() {
        return CurrencyEnum.ETH.currencyChainType;
    }
}